﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.ComponentModel;

namespace YuShiManageSystem.DATA
{
    public class DataModel : YuShiManageSystem.DATA.YSEntities
    {
        public event EventHandler OnSaveChanges;

        /// <summary>
        /// 保存数据库所有表关键字字段的当前最大值
        /// </summary>
        private static Dictionary<Type, int> _primaryKeysCache = new Dictionary<Type, int>();

        public static Dictionary<Type, int> primaryKeysCache
        {
            get
            {
                return _primaryKeysCache;
               
            }
        }

        #region 泛型相关方法

        /// <summary>
        /// 新生成一个数据表ID.
        /// </summary>
        /// <typeparam name="TEntity">实体对象类型.</typeparam>
        /// <param name="table">The table.</param>
        /// <param name="idSelector">The id selector.</param>
        /// <returns>返回一个新ID</returns>
        public static int GenerateID<TEntity>(
            Func<DataModel, ObjectQuery<TEntity>> table,
            Func<TEntity, int> idSelector) where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            lock (_primaryKeysCache)
            {

                int primaryKey = 0;
                if (!_primaryKeysCache.TryGetValue(typeof(TEntity), out primaryKey))
                {
                    using (DataModel model = new DataModel())
                    {
                        primaryKey = table(model).Any() ? table(model).Max(idSelector) : 0;
                    }
                }
                primaryKey++;
                _primaryKeysCache[typeof(TEntity)] = primaryKey;
                return primaryKey;
            }
        }

        /// <summary>
        /// Generates the ID.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns>返回一个新ID</returns>
        public static int GenerateID<TEntity>(TEntity entity)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            lock (_primaryKeysCache)
            {
                int primaryKey = 0;
                if (!_primaryKeysCache.TryGetValue(typeof(TEntity), out primaryKey))
                {
                    primaryKey = 0;
                }
                primaryKey++;
                _primaryKeysCache[typeof(TEntity)] = primaryKey;
                return primaryKey;
            }
        }

        /// <summary>
        /// Gets the search string.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns>返回生成的查询串</returns>
        private string getSearchString<TEntity>(TEntity entity)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            string condition = "";
            //string keyName = entity.EntityKey.EntityKeyValues[0].Key;
            Type entityType = entity.GetType();
            foreach (var fieldType in entityType.GetProperties())
            {
                if (!fieldType.CanWrite)
                    continue;
                if (fieldType.Name == "EntityState" || fieldType.Name == "EntityKey")
                    continue;
                var fieldValue = fieldType.GetValue(entity, null);
                if (fieldType.PropertyType.IsValueType)
                {
                    if (fieldValue != null)
                    {
                        if (fieldType.PropertyType.Name.StartsWith("Int"))//fieldType.Name == keyName && 
                        {
                            if ((int)fieldValue != 0)
                            {
                                if (condition != "")
                                    condition += " and ";
                                condition += "it." + fieldType.Name + "=" + fieldValue.ToString() + "";
                            }
                        }
                        else if (fieldType.PropertyType.FullName.Contains("System.Int") || fieldType.PropertyType.FullName.Contains("System.Decimal"))
                        {
                            if (condition != "")
                                condition += " and ";
                            condition += "it." + fieldType.Name + "=" + fieldValue.ToString() + "";
                        }
                        else if (fieldType.PropertyType.FullName.Contains("System.DateTime"))
                        {
                            if (condition != "")
                                condition += " and ";
                            System.DateTime value = (System.DateTime)fieldValue;
                            condition += "Year(it." + fieldType.Name + ")=" + value.Year + " and Month(it." + fieldType.Name + ")=" + value.Month + " and Day(it." + fieldType.Name + ")=" + value.Day;
                        }
                        else if (fieldType.PropertyType.FullName.Contains("Boolean"))
                        {
                            if (condition != "")
                                condition += " and ";
                            Boolean value = (Boolean)fieldValue;
                            condition += "it." + fieldType.Name + "=" + value.ToString();
                        }
                        else
                        {
                            //Console.WriteLine("“" + fieldType.PropertyType.FullName + "”数据库类型未找到");
                            //throw new Exception("“" + fieldType.PropertyType.FullName + "”数据库类型未找到");
                        }
                    }
                }
                else if (fieldType.PropertyType.Name == "String")
                {
                    if (fieldValue != null)
                    {
                        if (fieldValue.ToString() != "")
                        {
                            if (condition != "")
                                condition += " and ";
                            condition += "it." + fieldType.Name + " like '%" + fieldValue.ToString().Replace("'", "''") + "%'";
                        }
                    }
                }
            }
            return condition;
        }

        /// <summary>
        /// Searches the specified entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns>返回查询结果</returns>
        public ObjectQuery<TEntity> search<TEntity>(TEntity entity)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            string condition = getSearchString(entity);
            //System.Windows.Forms.MessageBox.Show(condition);
            Type thisType = this.GetType();
            ObjectQuery<TEntity> query = (ObjectQuery<TEntity>)(thisType.GetProperty(entity.GetType().Name).GetValue(new DataModel(), null));
            if (condition != "")
                query = query.Where(condition);
            return query;
        }



        /// <summary>
        /// Searches the specified query.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="query">The query.</param>
        /// <param name="entity">The entity.</param>
        /// <returns>返回生成的查询串</returns>
        public ObjectQuery<TEntity> search<TEntity>(ObjectQuery<TEntity> query, TEntity entity)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            string condition = getSearchString(entity);
            if (condition != "")
                query = query.Where(condition);
            Console.WriteLine(query.ToTraceString());
            return query;
        }

        /// <summary>
        /// Searches the specified entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <param name="orderField">The order field.</param>
        /// <returns>返回生成的查询串</returns>
        public ObjectQuery<TEntity> search<TEntity>(TEntity entity, string orderField)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            string condition = getSearchString(entity);
            Type thisType = this.GetType();
            ObjectQuery<TEntity> query = (ObjectQuery<TEntity>)(thisType.GetProperty(entity.GetType().Name).GetValue(new DataModel(), null));
            if (condition != "")
                query = query.Where(condition);
            if (orderField != "")
                query = query.OrderBy("it." + orderField);
            Console.WriteLine(query.ToTraceString());
            return query;
        }

        /// <summary>
        /// Searches the specified query.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="query">The query.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="orderField">The order field.</param>
        /// <returns>返回生成的查询串</returns>
        public ObjectQuery<TEntity> search<TEntity>(ObjectQuery<TEntity> query, TEntity entity, string orderField)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            string condition = getSearchString(entity);
            if (condition != "")
                query = query.Where(condition);
            if (orderField != "")
                query = query.OrderBy("it." + orderField);
            Console.WriteLine(query.ToTraceString());
            return query;
        }

        /// <summary>
        /// Searches the specified entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <param name="orderField">The order field.</param>
        /// <param name="direction">The direction.</param>
        /// <returns>返回生成的查询串</returns>
        public ObjectQuery<TEntity> search<TEntity>(TEntity entity, string orderField, ListSortDirection direction)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            string condition = getSearchString(entity);
            Type thisType = this.GetType();
            ObjectQuery<TEntity> query = (ObjectQuery<TEntity>)(thisType.GetProperty(entity.GetType().Name).GetValue(new DataModel(), null));
            if (condition != "")
                query = query.Where(condition);
            if (orderField != "")
                if (direction == ListSortDirection.Ascending)
                {
                    query = query.OrderBy("it." + orderField);
                }
                else
                {
                    query = query.OrderBy("it." + orderField + " desc");
                }
            Console.WriteLine(query.ToTraceString());
            return query;
        }

        /// <summary>
        /// Searches the specified query.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="query">The query.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="orderField">The order field.</param>
        /// <param name="direction">The direction.</param>
        /// <returns>返回生成的查询串</returns>
        public ObjectQuery<TEntity> search<TEntity>(ObjectQuery<TEntity> query, TEntity entity, string orderField, ListSortDirection direction)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            string condition = getSearchString(entity);
            if (condition != "")
                query = query.Where(condition);
            if (orderField != "")
                if (direction == ListSortDirection.Ascending)
                {
                    query = query.OrderBy("it." + orderField);
                }
                else
                {
                    query = query.OrderBy("it." + orderField + " desc");
                }
            Console.WriteLine(query.ToTraceString());
            return query;
        }

        /// <summary>
        /// Searches the specified entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <param name="fromDate">From date.</param>
        /// <param name="toDate">To date.</param>
        /// <returns>返回生成的查询串</returns>
        public ObjectQuery<TEntity> search<TEntity>(TEntity entity, String fromDate, String toDate)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            System.DateTime dateTime;
            string condition = getSearchString(entity);
            if (!String.IsNullOrEmpty(fromDate))
            {
                if (System.DateTime.TryParse(fromDate, out dateTime))
                {
                    if (condition != "")
                        condition += " and ";
                    condition += "it.created>=datetime'" + dateTime.Date + "'";
                }
            }
            if (!String.IsNullOrEmpty(toDate))
            {
                if (System.DateTime.TryParse(toDate, out dateTime))
                {
                    if (condition != "")
                        condition += " and ";
                    condition += "it.created<=datetime'" + dateTime.Date + "'";
                }
            }
            Type thisType = this.GetType();
            ObjectQuery<TEntity> query = (ObjectQuery<TEntity>)(thisType.GetProperty(entity.GetType().Name).GetValue(new DataModel(), null));
            if (condition != "")
                query = query.Where(condition);
            Console.WriteLine(query.ToTraceString());
            return query;
        }

        /// <summary>
        /// Inserts the or update object.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns>插入或更新记录数</returns>
        public int Save<TEntity>(TEntity entity)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            try
            {
                Type entityType = entity.GetType();
                if (entity.EntityState == System.Data.EntityState.Unchanged)
                    return 0;
                if (entity.EntityState == System.Data.EntityState.Detached | entity.EntityState == System.Data.EntityState.Added)
                {
                    //entityType.GetProperty(entity.EntityKey.EntityKeyValues[0].Key).SetValue(entity, GenerateID(entity), null);
                    string entityName = entity.ToString();
                    entityName = entityName.Substring(entityName.LastIndexOf('.') + 1);
                    //entityName = this.GetType().GetProperty(entityName) != null ? entityName : entityName + "s";
                    this.AddObject(entityName, entity);
                }
                if (OnSaveChanges != null)
                    OnSaveChanges(null, null);
                return this.SaveChanges();
            }
            catch (Exception ex)
            {
                if (entity != null && entity.EntityKey != null)
                {
                    if (entity.EntityState == System.Data.EntityState.Detached | entity.EntityState == System.Data.EntityState.Added)
                    {
                        this.Detach(entity);
                    }
                    else
                    {
                        this.Refresh(RefreshMode.StoreWins, entity);
                    }
                }
                Console.WriteLine(ex);
                throw;
            }
        }
        /// <summary>
        /// Inserts the or update object.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="entity">System.Data.Objects.DataClasses.EntityObject</param>
        /// <returns>插入或更新记录数</returns>
        public int Save(List<System.Data.Objects.DataClasses.EntityObject> entities) 
        {
            try
            {
                foreach (System.Data.Objects.DataClasses.EntityObject entity in entities)
                {
                    Type entityType = entity.GetType();
                    System.Windows.Forms.MessageBox.Show(entityType.Name);
                    if (entity.EntityState == System.Data.EntityState.Unchanged)
                        return 0;
                    if (entity.EntityState == System.Data.EntityState.Detached | entity.EntityState == System.Data.EntityState.Added)
                    {
                        string entityName = entity.ToString();
                        entityName = entityName.Substring(entityName.LastIndexOf('.') + 1);
                        this.AddObject(entityName, entity);
                       
                    } 
                }
                if (OnSaveChanges != null)
                    OnSaveChanges(null, null);
                return this.SaveChanges();
               
            }
            catch (Exception ex)
            {
                foreach (System.Data.Objects.DataClasses.EntityObject entity in entities)
                {
                    if (entity != null && entity.EntityKey != null)
                    {
                        if (entity.EntityState == System.Data.EntityState.Detached | entity.EntityState == System.Data.EntityState.Added)
                        {
                            this.Detach(entity);
                        }
                        else
                        {
                            this.Refresh(RefreshMode.StoreWins, entity);
                        }
                    } 
                }
                Console.WriteLine(ex);
                throw;
            }

            
            
        }
        /// <summary>
        /// 删除记录
        /// </summary>
        /// <param name="entity">所要删除的对象</param>
        /// <returns>删除的记录数</returns>
        /// 
        /// <typeparam name="TEntity"></typeparam><remarks></remarks>
        public int Delete<TEntity>(TEntity entity)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            try
            {
                if (entity.EntityKey == null)
                    throw new Exception("entity对象尚未附加");
                DeleteObject(entity);
                if (OnSaveChanges != null)
                    OnSaveChanges(null, null);
                return this.SaveChanges();
            }
            catch (Exception ex)
            {
                if (entity != null && entity.EntityKey != null)
                    this.Refresh(RefreshMode.StoreWins, entity);
                Console.WriteLine(ex);
                throw;
            }
        }

        /// <summary>
        /// Sorts the specified query.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="query">The query.</param>
        /// <param name="sortField">The sort field.</param>
        /// <returns>排序结果</returns>
        public ObjectQuery<TEntity> sort<TEntity>(ObjectQuery<TEntity> query, string sortField)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            try
            {
                ObjectQuery<TEntity> queryReturn = query.OrderBy("it." + sortField);
                //Console.WriteLine(queryReturn.ToTraceString());
                return queryReturn;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
        }

        /// <summary>
        /// Sorts the specified query.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="query">The query.</param>
        /// <param name="sortField">The sort field.</param>
        /// <param name="direction">The direction.</param>
        /// <returns>排序结果</returns>
        public ObjectQuery<TEntity> sort<TEntity>(ObjectQuery<TEntity> query, string sortField, ListSortDirection direction)
            where TEntity : System.Data.Objects.DataClasses.EntityObject
        {
            try
            {
                if (query == null || String.IsNullOrEmpty(sortField))
                    return query;
                string directionStr = (direction == ListSortDirection.Descending) ? " desc" : "";
                ObjectQuery<TEntity> queryReturn = query.OrderBy("it." + sortField + directionStr);
                Console.WriteLine(queryReturn.ToTraceString());
                return queryReturn;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
        }
        #endregion

        #region Store的相关方法
        public tb_store getUserByNameAndPassword(string name, string password)
		{
			try
			{
				return this.tb_store.Where(t => t.sName  == name && t.password == password ).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}
		#endregion

        #region customer的相关方法
        public tb_customer getCustomerByIdCard(string idCard)
        {
            try
            {
                return this.tb_customer.Where(t => idCard.Equals(t.idcard)).FirstOrDefault();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
        }
        #endregion

        #region card的相关方法
        public tb_card getCardByCard(string code)
        {
            try
            {
                return this.tb_card.Where(t => code.Equals(t.code)).FirstOrDefault();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
        }
        #endregion
    }
}
